package com.meilai.project.service.personnel.org.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.dto.personnel.org.RoleDTO;
import com.meilai.project.entity.personnel.org.Role;
import com.meilai.project.entity.system.RoleMiniRightRelation;
import com.meilai.project.entity.system.RoleRouterRelation;
import com.meilai.project.entity.system.Router;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.personnel.org.RoleMapper;
import com.meilai.project.service.personnel.org.RoleService;
import com.meilai.project.service.system.*;
import com.meilai.project.vo.personnel.org.WebRoleVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 张驰
 * @date 2020/9/11 13:15
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role>  implements RoleService {

    @Autowired
    private RouterService routerService;

    @Autowired
    private UserRoleRelationService userRoleRelationService;

    @Autowired
    private RoleRouterRelationService roleRouterRelationService;

    @Autowired
    private RoleMiniRightRelationService roleMiniRightRelationService;

    @Override
    public Page<WebRoleVO> selectPageList(Integer current_page, Integer page_size, String name, Integer status) {
        Page<WebRoleVO> page = new Page<WebRoleVO>(current_page,page_size);
        List<WebRoleVO> list = baseMapper.selectPageList(page,name,status);
        return page.setRecords(list);
    }

    @Override
    @Transactional
    public int addOne(RoleDTO dto) {
        Role temp = new Role();
        BeanUtils.copyProperties(dto, temp);
        boolean flag = save(temp)
                && updateRouterRelation(temp.getId(),dto.getRouterIds())
                && updateMiniRightRelation(temp.getId(),dto.getMiniRightIds());
        return flag?1:0;
    }

    @Override
    @Transactional
    public int editOne(RoleDTO dto) {
        if (dto.getId() == null) return 0;
        Role temp = baseMapper.selectById(dto.getId());
        if (temp == null) return 0;
        Role _temp = new Role();
        BeanUtils.copyProperties(dto, _temp);
        boolean flag = baseMapper.updateById(_temp)==1
                && updateRouterRelation(_temp.getId(),dto.getRouterIds())
                && updateMiniRightRelation(_temp.getId(),dto.getMiniRightIds());
        return flag?1:0;
    }

    private boolean updateRouterRelation(Long roleId, List<Long> routerIds){
        boolean flag = true;
        if(routerIds == null || routerIds.size() <= 0) return flag;
        roleRouterRelationService.remove(new QueryWrapper<RoleRouterRelation>().eq("role_id",roleId));
        List<RoleRouterRelation> relations = routerIds.stream().map(item -> {
            RoleRouterRelation temp = new RoleRouterRelation();
            temp.setRole_id(roleId);
            temp.setRouter_id(item);
            return temp;
        }).collect(Collectors.toList());

        // 隐藏的路由自动加入
        List<Router> hiddenMenus = routerService.list(new QueryWrapper<Router>().isNull("deleted_at").eq("status",1).in("p_menu_id",routerIds));
        if(hiddenMenus != null && hiddenMenus.size() > 0){
            List<RoleRouterRelation> hiddenRelations = hiddenMenus.stream().map(item -> {
                RoleRouterRelation temp = new RoleRouterRelation();
                temp.setRole_id(roleId);
                temp.setRouter_id(item.getId());
                return temp;
            }).collect(Collectors.toList());
            relations.addAll(hiddenRelations);
        }

        flag = flag && roleRouterRelationService.saveBatch(relations);
        return flag;
    }

    private boolean updateMiniRightRelation(Long roleId, List<Long> rightIds){
        boolean flag = true;
        if(rightIds == null || rightIds.size() <= 0) return flag;
        roleMiniRightRelationService.remove(new QueryWrapper<RoleMiniRightRelation>().eq("role_id",roleId));
        List<RoleMiniRightRelation> relations = rightIds.stream().map(item -> {
            RoleMiniRightRelation temp = new RoleMiniRightRelation();
            temp.setRole_id(roleId);
            temp.setRight_id(item);
            return temp;
        }).collect(Collectors.toList());

        flag = flag && roleMiniRightRelationService.saveBatch(relations);
        return flag;
    }

    @Override
    @Transactional
    public Boolean del(List<Long> ids) {
        Integer count = userRoleRelationService.countUserRelationByRoleId(ids);
        if(count > 0) throw new CommonException("存在关联用户，无法删除");
        return update(new UpdateWrapper<Role>().set("deleted_at",LocalDateTime.now()).in("id",ids));
    }

    @Override
    @Transactional
    public Boolean changeStatus(Long id, Integer status) {
        Role temp = baseMapper.selectById(id);
        if (temp == null) {
            return false;
        }
        Role _temp = new Role();
        _temp.setId(id);
        _temp.setStatus(status);
        return baseMapper.updateById(_temp) > 0;
    }

    @Override
    public RoleDTO selectDetail(Long id) {
        RoleDTO dto = new RoleDTO();
        Role role = getById(id);
        if(role == null) return dto;
        BeanUtils.copyProperties(role,dto);
        List<RoleRouterRelation> relations = roleRouterRelationService.list(new QueryWrapper<RoleRouterRelation>().eq("role_id",id));
        if(relations == null || relations.size() <= 0) {
            dto.setRouterIds(new ArrayList<>());
        }else{
            dto.setRouterIds(relations.stream().map(RoleRouterRelation::getRouter_id).collect(Collectors.toList()));
        }
        return dto;
    }

    @Override
    public List<WebRoleVO> selectOptionList() {
        return baseMapper.selectOptionList();
    }

    @Override
    public boolean checkCodeUnique(String code, boolean is_edit, Long id) {
        QueryWrapper<Role> qw = new QueryWrapper<>();
        qw.isNull("deleted_at");
        qw.eq("code", code);
        if(is_edit) qw.ne("id", id);
        return count(qw) > 0;
    }

    @Override
    public Role getRoleByCode(String code) {
        return getOne(new QueryWrapper<Role>().eq("code",code)
                .isNull("deleted_at").eq("status",1));
    }
}
